package com.sfang.common.util.http;


import com.sfang.common.base.collection.CustomKeyValuePair;
import com.sfang.common.base.entity.RestInfo;
import com.sfang.common.base.enums.OauthStatus;
import com.sfang.common.base.enums.ResultStatus;

import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * Created by psalmody on 2016/9/2.
 */
public class RestfulUtil {


    public static <T> RestInfo<T> successRes(T t) {
        RestInfo<T> restInfo = new RestInfo<T>();
        restInfo.setSuccess(true);

        restInfo.setMsg("操作成功");
        restInfo.setData(t);
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Success.ordinal());
        return restInfo;
    }

    public static <T> RestInfo<T> successRes(T t, long totalCount) {
        RestInfo<T> restInfo = new RestInfo<T>();
        restInfo.setSuccess(true);
        restInfo.setTotalCount(totalCount);
        restInfo.setMsg("操作成功");
        restInfo.setData(t);
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Success.ordinal());
        return restInfo;
    }

    public static <T> RestInfo<T> successWithResponse(T t) {
        RestInfo<T> restInfo = new RestInfo<T>();
        restInfo.setSuccess(true);

        restInfo.setMsg("操作成功");
        restInfo.setResponse(t);
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Success.ordinal());
        return restInfo;
    }

    public static <T> RestInfo<CustomKeyValuePair> successPageInfo(List<T> ts, Integer pageIndex, Integer pageSize, Consumer<List<T>> consumer, Comparator<T> comparator) {

        if (comparator != null)
            ts = ts.stream().sorted(comparator).collect(Collectors.toList());

        List<T> datas = pageIndex == null ? ts : ts.stream().skip((pageIndex - 1) * pageSize).limit(pageSize).collect(Collectors.toList());

        if (consumer != null && datas.size() > 0)
            consumer.accept(datas);

        return successRes(CustomKeyValuePair.create(datas, ts.size()));
    }

    public static <T> RestInfo<CustomKeyValuePair> successPageInfo(List<T> ts, Integer pageIndex, Integer pageSize,
                                                                   Consumer<List<T>> consumer,
                                                                   Predicate<T> predicate,
                                                                   Comparator<T> comparator) {

        if (comparator != null)
            ts = predicate == null
                    ? ts.stream().sorted(comparator).collect(Collectors.toList())
                    : ts.stream().filter(predicate).sorted(comparator).collect(Collectors.toList());

        List<T> datas = pageIndex == null ? ts : ts.stream().skip((pageIndex - 1) * pageSize).limit(pageSize).collect(Collectors.toList());

        if (consumer != null && datas.size() > 0)
            consumer.accept(datas);

        return successRes(CustomKeyValuePair.create(datas, ts.size()));
    }

    public static RestInfo successRes() {
        RestInfo restInfo = new RestInfo();
        restInfo.setSuccess(true);

        restInfo.setMsg("操作成功");
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Success.ordinal());

        RestInfo.InnerSuccess innerSuccess = new RestInfo.InnerSuccess();
        innerSuccess.setIsSuccess(true);

        restInfo.setData(innerSuccess);
        return restInfo;
    }


    public static <T> RestInfo<T> successRes(T t, String msg) {
        RestInfo<T> restInfo = new RestInfo<T>();
        restInfo.setSuccess(true);

        restInfo.setMsg(msg);
        restInfo.setData(t);
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Success.ordinal());
        return restInfo;
    }

    public static RestInfo failRes() {
        RestInfo restInfo = new RestInfo();
        restInfo.setSuccess(false);

        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Fail.ordinal());

        RestInfo.ErrorResponse errorResponse = new RestInfo.ErrorResponse();
        errorResponse.setCode(ResultStatus.BizError.getStatus());
        restInfo.setErrorResponse(errorResponse);

        return restInfo;
    }

    public static <T> RestInfo<T> failRes(T t) {
        RestInfo restInfo = new RestInfo();
        restInfo.setSuccess(false);

        restInfo.setData(t);
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Fail.ordinal());

        RestInfo.ErrorResponse errorResponse = new RestInfo.ErrorResponse();
        errorResponse.setCode(ResultStatus.BizError.getStatus());
        restInfo.setErrorResponse(errorResponse);

        return restInfo;
    }

    public static <T> RestInfo<T> failRes(ResultStatus resultStatus) {
        RestInfo restInfo = new RestInfo();
        restInfo.setSuccess(false);

        restInfo.setServerTime(new Date());
        restInfo.setStatus(resultStatus.ordinal());

        RestInfo.ErrorResponse errorResponse = new RestInfo.ErrorResponse();
        errorResponse.setCode(ResultStatus.BizError.getStatus());
        restInfo.setErrorResponse(errorResponse);

        return restInfo;
    }

    public static <T> RestInfo<T> successRes(String msg, Integer businessCode, T t) {
        RestInfo<T> restInfo = new RestInfo<T>();
        restInfo.setSuccess(true);

        restInfo.setMsg(msg);
        restInfo.setData(t);
        restInfo.setCode(businessCode);
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Success.ordinal());
        return restInfo;
    }

    public static <T> RestInfo<T> successRes(Integer businessCode, T t) {
        RestInfo<T> restInfo = new RestInfo<T>();
        restInfo.setSuccess(true);

        restInfo.setData(t);
        restInfo.setCode(businessCode);
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Success.ordinal());
        return restInfo;
    }

    public static RestInfo successResWithResult(String result) {
        RestInfo restInfo = new RestInfo();
        restInfo.setSuccess(true);

        restInfo.setMsg("操作成功!");
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Success.getStatus());
        restInfo.setData(result);
        return restInfo;
    }

    public static RestInfo successResWithResult(String msg, int businessCode) {
        RestInfo restInfo = new RestInfo();
        restInfo.setSuccess(true);
        restInfo.setMsg(msg);
        restInfo.setServerTime(new Date());
        restInfo.setCode(businessCode);
        restInfo.setStatus(ResultStatus.Success.ordinal());
        return restInfo;
    }

    public static RestInfo failRes(String msg) {
        RestInfo restInfo = new RestInfo();
        restInfo.setSuccess(false);

        restInfo.setMsg(msg);
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Fail.ordinal());

        RestInfo.ErrorResponse errorResponse = new RestInfo.ErrorResponse();
        errorResponse.setCode(ResultStatus.BizError.getStatus());
        errorResponse.setMessage(msg);
        restInfo.setErrorResponse(errorResponse);

        RestInfo.InnerSuccess innerSuccess = new RestInfo.InnerSuccess();
        innerSuccess.setIsSuccess(false);

        restInfo.setData(innerSuccess);

        return restInfo;
    }

    public static <T> RestInfo failWithResult(String msg, T result) {
        RestInfo restInfo = new RestInfo();
        restInfo.setSuccess(false);
        restInfo.setData(result);
        restInfo.setMsg(msg);
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Fail.ordinal());

        RestInfo.ErrorResponse errorResponse = new RestInfo.ErrorResponse();
        errorResponse.setCode(ResultStatus.BizError.getStatus());
        errorResponse.setMessage(msg);
        restInfo.setErrorResponse(errorResponse);
        return restInfo;
    }


    public static RestInfo failResWithStatus(String msg, int status) {
        RestInfo restInfo = new RestInfo();
        restInfo.setSuccess(false);
        restInfo.setStatus(status);
        restInfo.setMsg(msg);
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Fail.ordinal());

        RestInfo.ErrorResponse errorResponse = new RestInfo.ErrorResponse();
        errorResponse.setCode(ResultStatus.BizError.getStatus());
        errorResponse.setMessage(msg);
        restInfo.setErrorResponse(errorResponse);

        return restInfo;
    }

    public static RestInfo failRes(String msg, int businessCode) {
        RestInfo restInfo = new RestInfo();
        restInfo.setSuccess(false);

        restInfo.setMsg(msg);
        restInfo.setCode(businessCode);
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Fail.ordinal());

        RestInfo.ErrorResponse errorResponse = new RestInfo.ErrorResponse();
        errorResponse.setCode(ResultStatus.BizError.getStatus());
        errorResponse.setMessage(msg);
        restInfo.setErrorResponse(errorResponse);

        return restInfo;
    }


    public static RestInfo failRes(String msg, String errorCode) {
        RestInfo restInfo = new RestInfo();
        restInfo.setSuccess(false);

        restInfo.setMsg(msg);
        restInfo.setErrorCode(errorCode);
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Fail.ordinal());

        RestInfo.ErrorResponse errorResponse = new RestInfo.ErrorResponse();
        errorResponse.setCode(ResultStatus.BizError.getStatus());
        errorResponse.setMessage(msg);
        restInfo.setErrorResponse(errorResponse);

        return restInfo;
    }

    public static <T> RestInfo<T> failRes(String msg, int businessCode, T t) {
        RestInfo restInfo = new RestInfo();
        restInfo.setSuccess(false);
        restInfo.setData(t);
        restInfo.setMsg(msg);
        restInfo.setCode(businessCode);
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Fail.ordinal());

        RestInfo.ErrorResponse errorResponse = new RestInfo.ErrorResponse();
        errorResponse.setCode(ResultStatus.BizError.getStatus());
        errorResponse.setMessage(msg);
        restInfo.setErrorResponse(errorResponse);

        return restInfo;
    }

    public static RestInfo failResWithResult(String msg, Object result) {
        RestInfo restInfo = new RestInfo();
        restInfo.setSuccess(false);

        restInfo.setMsg(msg);
        restInfo.setServerTime(new Date());
        restInfo.setStatus(ResultStatus.Fail.getStatus());
        restInfo.setData(result);

        RestInfo.ErrorResponse errorResponse = new RestInfo.ErrorResponse();
        errorResponse.setCode(ResultStatus.BizError.getStatus());
        errorResponse.setMessage(msg);
        restInfo.setErrorResponse(errorResponse);

        return restInfo;
    }

    public static RestInfo failResWithErrorResponse(Integer code, String subCode, String msg) {
        RestInfo restInfo = new RestInfo();
        restInfo.setCode(code);
        RestInfo.ErrorResponse errorResponse = new RestInfo.ErrorResponse();

        if (OauthStatus.InvalidToken.getCode().equalsIgnoreCase(String.valueOf(code)))
            errorResponse.setCode(code);
        else
            errorResponse.setCode(ResultStatus.BizError.getStatus());

        errorResponse.setSubCode(subCode);
        errorResponse.setMessage(msg);
        restInfo.setErrorResponse(errorResponse);
        return restInfo;
    }

    public static RestInfo failResWithErrorResponse(String code, String subCode, String msg) {
        RestInfo restInfo = new RestInfo();
        restInfo.setCode(Integer.valueOf(code));
        RestInfo.ErrorResponse errorResponse = new RestInfo.ErrorResponse();
        errorResponse.setCode(Integer.valueOf(code));
        errorResponse.setSubCode(subCode);
        errorResponse.setMessage(msg);
        restInfo.setErrorResponse(errorResponse);
        return restInfo;
    }

    public static RestInfo failResWithServerErrorResponse(String code, String subCode, String msg) {
        RestInfo restInfo = new RestInfo();
        restInfo.setCode(Integer.valueOf(code));
        RestInfo.ErrorResponse errorResponse = new RestInfo.ErrorResponse();
        errorResponse.setCode(ResultStatus.BizError.getStatus());
        errorResponse.setSubCode(subCode);
        errorResponse.setMessage(msg);
        restInfo.setErrorResponse(errorResponse);
        return restInfo;
    }


}
